package com.zzttwl.locktcp.start;


import com.zzttwl.locktcp.handler.ServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.bytes.ByteArrayDecoder;
import io.netty.handler.codec.bytes.ByteArrayEncoder;
import org.apache.log4j.Logger;


public class Server {

    private Logger logger = Logger.getLogger(Server.class);

    private class ChildChannelHandler extends ChannelInitializer<SocketChannel> {

        @Override
        protected void initChannel(SocketChannel ch) throws Exception {
			/*ch.pipeline().addLast(new StringEncoder(Charset.forName("UTF-8")));//字符串编码
			ch.pipeline().addLast(new StringDecoder(Charset.forName("UTF-8")));//字符串解码
			ch.pipeline().addLast(new ByteArrayEncoder());//byte[]数组编码
			ch.pipeline().addLast(new ByteArrayDecoder());//byte[]数组解码
			ch.pipeline().addLast(new ServerHandler());*/

            ChannelPipeline pipeline = ch.pipeline();
            pipeline.addLast("bytesDecoder", new ByteArrayDecoder());
            pipeline.addLast("bytesEncoder", new ByteArrayEncoder());

            pipeline.addLast("handler", new ServerHandler());
        }
    }

    /**
     * Windows系统通过此方法启动
     *
     * @param port
     * @author xubaisen
     */
    public void bindWindowsBootstrap(int port) {
        // 配置服务端线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup).option(ChannelOption.SO_BACKLOG, 50 * 1024)
                .childOption(ChannelOption.TCP_NODELAY, true).channel(NioServerSocketChannel.class)
                .childOption(ChannelOption.SO_KEEPALIVE, true).childHandler(new ChildChannelHandler());

        try {
            // 绑定端口，同步等待成功
            ChannelFuture f = b.bind(port).sync();
            logger.warn("成功启动服务器");
            // 等待服务端监听端口关闭
            f.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 优雅退出，释放线程池资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    /**
     * Linux系统通过此方法启动
     *
     * @param port
     * @author xubaisen
     */
    public void bindLinuxBootstrap(int port) {
        // 配置服务端线程组
        EventLoopGroup bossGroup = new EpollEventLoopGroup();
        EventLoopGroup workerGroup = new EpollEventLoopGroup();

        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup)
                .channel(EpollServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 50 * 1024)
//		.option(EpollChannelOption.SO_REUSEPORT, true)
                .childOption(ChannelOption.TCP_NODELAY, true)
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childHandler(new ChildChannelHandler());

        try {
            // 绑定端口，同步等待成功
            ChannelFuture f = b.bind(port).sync();
            logger.info("成功启动服务器");
            // 等待服务端监听端口关闭
            f.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 优雅退出，释放线程池资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
